package ace.cmp.spring.data.jdbc.querydsl.core.repository;

import ace.cmp.core.exception.BusinessI18nException;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;
import com.querydsl.sql.RelationalPathBase;
import jakarta.annotation.Nonnull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

/**
 * @author caspar
 * @date 2023/4/3 13:58
 */
public interface QuerydslJdbcBaseFragment<T, Id> {

  /**
   * 添加数据,映射全部字段(包含null字段),启用框架注解处理 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间
   * {@link org.springframework.data.annotation.Version} 版本号乐观锁 {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entity 保存的实体
   * @return 影响行数
   */
  long insert(T entity);

  /**
   * 添加数据 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间 {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entity            保存的实体
   * @param saveNullFieldFlag 是否保存null的字段
   * @return 影响行数
   */
  long insert(T entity, boolean saveNullFieldFlag);

  /**
   * 添加数据 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间 {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entity                      保存的实体
   * @param saveNullFieldFlag           是否保存null的字段
   * @param enableVersionForce          是否强制使用框架值
   * @param enableCreatedDateForce      是否强制使用框架值
   * @param enableLastModifiedDateForce 是否最后修改时间强制使用框架
   * @param enableLogicDeleteForce      是否强制使用框架值
   * @return 影响行数
   */
  long insert(
      T entity,
      boolean saveNullFieldFlag,
      boolean enableVersionForce,
      boolean enableCreatedDateForce,
      boolean enableLastModifiedDateForce,
      boolean enableLogicDeleteForce);

  /**
   * 添加数据,映射全部字段(包含null字段) {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间
   * {@link org.springframework.data.annotation.Version} 版本号乐观锁 {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entities 保存的实体集合
   * @return 影响行数
   */
  long insert(Collection<T> entities);

  /**
   * 添加数据 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间 {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entities          保存的实体
   * @param saveNullFieldFlag 是否保存null的字段
   * @return 影响行数
   */
  long insert(Collection<T> entities, boolean saveNullFieldFlag);

  /**
   * 添加数据，不保存null字段,并自动注入框架字段.
   *
   * {@link org.springframework.data.annotation.CreatedDate} 创建时间
   * {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间
   * {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entities                    保存的实体
   * @return 影响行数
   */
  long insertNotNullFieldAndInjectFrameworkField(Collection<T> entities);

  /**
   * 添加数据，不保存null字段,并自动注入框架字段.
   *
   * {@link org.springframework.data.annotation.CreatedDate} 创建时间
   * {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间
   * {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entity                    保存的实体
   * @return 影响行数
   */
  long insertNotNullFieldAndInjectFrameworkField(T entity);

  /**
   * 添加数据 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间 {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entities                    保存的实体
   * @param saveNullFieldFlag           是否保存null的字段
   * @param enableVersionForce          是否强制使用框架值
   * @param enableCreatedDateForce      是否强制使用框架值
   * @param enableLastModifiedDateForce 是否最后修改时间强制使用框架
   * @param enableLogicDeleteForce      是否强制使用框架值
   * @return 影响行数
   */
  long insert(
      Collection<T> entities,
      boolean saveNullFieldFlag,
      boolean enableVersionForce,
      boolean enableCreatedDateForce,
      boolean enableLastModifiedDateForce,
      boolean enableLogicDeleteForce);


  /**
   * 修改数据,映射全部字段(包含null字段),启用框架注解处理 {@link org.springframework.data.annotation.Version} 版本号乐观锁 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时
   *
   * @param entity 修改实体
   * @return 影响行数
   */
  long updateById(T entity);

  /**
   * 修改数据,启用框架注解处理 {@link org.springframework.data.annotation.Version} 版本号乐观锁 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时
   *
   * @param entity            修改实体
   * @param saveNullFieldFlag 是否保存null的字段
   * @return 影响行数
   */
  long updateById(T entity, boolean saveNullFieldFlag);

  /**
   * 修改数据 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间 {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entity                      实体
   * @param saveNullFieldFlag           是否保存null字段
   * @param enableVersionOnlyUpdate     启用版本号注解,仅自动更新版本号,不进行版本号过滤
   * @param enableCreatedDateForce      启用创建时间注解,忽略用户提交的值
   * @param enableLastModifiedDateForce 启用最后修改时间注解,忽略用户提交的值
   * @param enableLogicDeleteForce      启用逻辑删除注解,忽略用户提交的值
   * @return 影响行数
   */
  long updateById(
      T entity,
      boolean saveNullFieldFlag,
      boolean enableVersionOnlyUpdate,
      boolean enableCreatedDateForce,
      boolean enableLastModifiedDateForce,
      boolean enableLogicDeleteForce);

  /**
   * 修改数据 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间 {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entities 实体
   * @return 影响行数
   */
  long updateById(Collection<T> entities);

  /**
   * 修改数据 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间 {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entities          实体
   * @param saveNullFieldFlag 是否保存null字段
   * @return 影响行数
   */
  long updateById(Collection<T> entities, boolean saveNullFieldFlag);

  /**
   * 修改数据 {@link org.springframework.data.annotation.CreatedDate} 创建时间 {@link org.springframework.data.annotation.LastModifiedDate} 最后修改时间 {@link org.springframework.data.annotation.Version} 版本号乐观锁
   * {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete} 逻辑删除
   *
   * @param entities                    实体
   * @param saveNullFieldFlag           是否保存null字段
   * @param enableVersionOnlyUpdate     启用版本号注解,仅自动更新版本号,不进行版本号过滤
   * @param enableCreatedDateForce      启用创建时间注解,忽略用户提交的值
   * @param enableLastModifiedDateForce 启用最后修改时间注解,忽略用户提交的值
   * @param enableLogicDeleteForce      启用逻辑删除注解,忽略用户提交的值
   * @return 影响行数
   */
  long updateById(
      Collection<T> entities,
      boolean saveNullFieldFlag,
      boolean enableVersionOnlyUpdate,
      boolean enableCreatedDateForce,
      boolean enableLastModifiedDateForce,
      boolean enableLogicDeleteForce);

  /**
   * 逻辑删除
   *
   * @param ids id集合
   * @return 影响行数
   */
  long deleteLogicById(Collection<Id> ids);

  long deleteLogicBy(Predicate predicate);

  /**
   * 逻辑删除
   *
   * @param ids id集合
   * @return 影响行数
   */
  long deleteLogicById(Id... ids);

  long deleteLogicByIdForEntity(Collection<T> entities);

  long deleteLogicByIdForEntity(T entity);

  /**
   * 根据id,查询对象
   *
   * @param ids id
   * @return 返回Map对象，key:id,value:object
   */
  Map<Id, T> findAllMapByIds(Collection<Id> ids);

  Map<Id, T> findAllMapBy(Predicate predicate);

  Map<Id, T> findAllMapBy(Predicate predicate, Sort sort);

  Map<Id, T> findAllMapBy(Predicate predicate, OrderSpecifier<?>... orderSpecifiers);

  T getById(Id id);

  List<T> getByIdIn(Collection<Id> ids);

  /**
   * 根据id获取没有逻辑删除的实体
   *
   * @param id
   */
  T findByIdAndDeleteFlagIsNot(Id id);

  /**
   * 根据id获取没有逻辑删除的实体.
   *
   * @param ids id list
   */
  List<T> findByIdInAndDeleteFlagIsNot(Collection<Id> ids);

  /**
   * 根据id获取没有逻辑删除的实体,并检查实体不为null
   *
   * @param id
   * @return {@link T}
   * @throws {@link ace.cmp.core.exception.BusinessI18nException}
   */
  @Nonnull
  T findAndCheckDataIsNotNullByIdAndDeleteFlagIsNot(Id id);

  /**
   * 根据id获取实体,并检查实体不为null
   *
   * @param id
   * @return {@link T}
   * @throws {@link BusinessI18nException}
   */
  @Nonnull
  T findAndCheckDataIsNotNullById(Id id);

  /**
   * 分页.
   *
   * @param predicate 查询条件
   * @param pageable  分页参数
   * @return 分页结果
   */
  Page<T> page(Predicate predicate, Pageable pageable);

  /**
   * 分页.
   *
   * @param entityPath 实体别名
   * @param predicate  查询条件
   * @param pageable   分页参数
   * @return 分页结果
   */
  Page<T> page(RelationalPathBase<T> entityPath, Predicate predicate, Pageable pageable);

  /**
   * 分页.
   *
   * @param predicates 查询条件
   * @param pageable   分页参数
   * @return 分页结果
   */
  Page<T> page(Collection<Predicate> predicates, Pageable pageable);

  /**
   * 分页.
   *
   * @param entityPath 实体别名
   * @param predicates 查询条件
   * @param pageable   分页参数
   * @return 分页结果
   */
  Page<T> page(RelationalPathBase<T> entityPath, Collection<Predicate> predicates,
      Pageable pageable);


  /**
   * 分页.
   *
   * @param pageable 分页参数
   * @return 分页结果
   */
  Page<T> page(Pageable pageable);

  /**
   * 查询数量.
   *
   * @param ids ids
   * @return 存在数量
   */
  long countByIdIn(List<Id> ids);

  Class<T> getEntityClass();

  Class<Id> getIdClass();

}
